﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using YArchitech.HVAC;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using HYCreateDuct.FormDuct;
using HYCreateDuct.MethodHelp;

namespace HYCreateDuct.MethodCreateDuct
{
	internal class CreateDuct
	{
		public static Duct CreateDuctStruct(Autodesk.Revit.DB.Document doc, DuctWindowStruct cs, List<DuctSytemSet> lstCurrentOut, double offset)
		{
			ElementId elementId3;
			ElementId elementId2;
			ElementId elementId = elementId2 = (elementId3 = ElementId.InvalidElementId);
			ElementClassFilter elementClassFilter = new ElementClassFilter(typeof(Level));
			foreach (Element element in new FilteredElementCollector(doc).WherePasses(elementClassFilter))
			{
				if (element.Name == cs.strLevel)
				{
					elementId3 = element.Id;
					break;
				}
			}
			if (elementId3 == ElementId.InvalidElementId)
			{
				throw new Exception("无法生成风管，参数错误");
			}
			int i = 0;
			DuctSytemSet item = null;
			for (int j = 0; j < lstCurrentOut.Count; j++)
			{
				if (lstCurrentOut[j].strSystemName.Equals(cs.strSystemType))
				{
					item = lstCurrentOut[j];
					i = j;
				}
			}
			if (lstCurrentOut.Count > 0 && cs.nInnerType == 1)
			{
				new FormDuctSet(doc).UpdateSystemDuctType(doc, item, i, ref CreateDuct.blTishi);
			}
			ElementClassFilter elementClassFilter2 = new ElementClassFilter(typeof(MEPSystemType));
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc).WherePasses(elementClassFilter2);
			new List<MEPSystemType>();
			foreach (Element element2 in filteredElementCollector)
			{
				MEPSystemType mepsystemType = (MEPSystemType)element2;
				string name = mepsystemType.Name;
				if (mepsystemType.Name.Contains(" "))
				{
					name = mepsystemType.Name.Substring(0, mepsystemType.Name.IndexOf(' '));
					mepsystemType.Name = name;
				}
				if (mepsystemType.Name.Equals(cs.strSystemType))
				{
					elementId2 = mepsystemType.Id;
					break;
				}
			}
			if (elementId2 == ElementId.InvalidElementId)
			{
				throw new Exception("无法找到系统类型");
			}
			ElementClassFilter elementClassFilter3 = new ElementClassFilter(typeof(DuctType));
			foreach (Element element3 in new FilteredElementCollector(doc).WherePasses(elementClassFilter3))
			{
				DuctType ductType = (DuctType)element3;
				if ((ductType.FamilyName + "-" + ductType.Name).Equals(cs.strDuctType))
				{
					elementId = ductType.Id;
					break;
				}
			}
			Duct duct = Duct.Create(doc, elementId2, elementId, elementId3, new XYZ(0.0, 0.0, 0.0), new XYZ(100.0, 0.0, 0.0));
			foreach (object obj in duct.Parameters)
			{
				Parameter parameter = (Parameter)obj;
				if (parameter.Definition.Name == "宽度" && !parameter.IsReadOnly)
				{
					double num = parameter.AsDouble();
					num = cs.dDuctWidth / 304.8;
					parameter.Set(num);
				}
				if (parameter.Definition.Name == "高度" && !parameter.IsReadOnly)
				{
					double num2 = parameter.AsDouble();
					num2 = cs.dDuctHeight / 304.8;
					parameter.Set(num2);
				}
				if (parameter.Definition.Name == "直径" && !parameter.IsReadOnly)
				{
					double num3 = parameter.AsDouble();
					num3 = cs.dDuctWidth / 304.8;
					parameter.Set(num3);
				}
				if (parameter.Definition.Name == "偏移量" || (parameter.Definition.Name == "偏移" && !parameter.IsReadOnly))
				{
					double num4 = parameter.AsDouble();
					num4 = cs.dOffset / 304.8 - offset;
					parameter.Set(num4);
				}
				if (parameter.Definition.Name == "水平对正" && !parameter.IsReadOnly)
				{
					parameter.Set(0);
				}
				if (parameter.Definition.Name == "垂直对正" && !parameter.IsReadOnly)
				{
					parameter.Set(0);
				}
			}
            doc.SetDefaultElementTypeId((ElementTypeGroup)97, elementId);
			return duct;
		}

		public static List<Duct> CreateListDuct(Duct duct, List<Curve> lstCurve, double offset, double offsetLevel)
		{
			List<Duct> list = new List<Duct>();
			int i = 0;
			while (i < lstCurve.Count)
			{
				Duct duct2 = null;
				if (offset == 0.0)
				{
					duct2 = YJKRevitTools.NewDuct(duct, lstCurve[i].GetEndPoint(0), lstCurve[i].GetEndPoint(1));
					IEnumerator enumerator = duct2.Parameters.GetEnumerator();
					{
						while (enumerator.MoveNext())
						{
							object obj = enumerator.Current;
							Parameter parameter = (Parameter)obj;
							if (parameter.Definition.Name == "偏移量" || (parameter.Definition.Name == "偏移" && !parameter.IsReadOnly))
							{
								double num = parameter.AsDouble();
								num = lstCurve[i].GetEndPoint(0).Z;
								parameter.Set(num - offsetLevel);
								break;
							}
						}
						goto IL_28F;
					}
					goto IL_E2;
				}
				goto IL_E2;
				IL_28F:
				if (duct2 != null)
				{
					list.Add(duct2);
				}
				i++;
				continue;
				IL_E2:
				XYZ endPoint = lstCurve[i].GetEndPoint(0);
				XYZ endPoint2 = lstCurve[i].GetEndPoint(1);
				XYZ newXYZDeriction = YJKRevitTools.getNewXYZDeriction(endPoint, endPoint2);
				Line pipeline = YJKLineEx.YJKGetBound(endPoint, endPoint2);
				XYZ xyz = CreateDuct.getNewParallelPipeXYZ(endPoint, pipeline, offset, newXYZDeriction);
				XYZ endXYZ = CreateDuct.getNewParallelPipeXYZ(endPoint2, pipeline, offset, newXYZDeriction);
				if (Math.Abs(endPoint.X - endPoint2.X) < 0.0001 && Math.Abs(endPoint.Y - endPoint2.Y) < 0.0001 && Math.Abs(endPoint.Z - endPoint2.Z) > 0.015)
				{
					xyz = new XYZ(endPoint.X + offset / 304.8, endPoint.Y, endPoint.Z);
					endXYZ = new XYZ(endPoint2.X + offset / 304.8, endPoint2.Y, endPoint2.Z);
					duct2 = YJKRevitTools.NewDuct(duct, xyz, endXYZ);
					goto IL_28F;
				}
				duct2 = YJKRevitTools.NewDuct(duct, xyz, endXYZ);
				foreach (object obj2 in duct2.Parameters)
				{
					Parameter parameter2 = (Parameter)obj2;
					if (parameter2.Definition.Name == "偏移量" || (parameter2.Definition.Name == "偏移" && !parameter2.IsReadOnly))
					{
						double num2 = parameter2.AsDouble();
						num2 = xyz.Z;
						parameter2.Set(num2 - offsetLevel);
						break;
					}
				}
				goto IL_28F;
			}
			return list;
		}

		public static bool ConnectDuct(Autodesk.Revit.DB.Document doc, DuctWindowStruct cs, List<Duct> lstDuct, List<Duct> lstDuctAll)
		{
			HYDuctConnect hyductConnect = new HYDuctConnect();
			if (lstDuct.Count == 1 && lstDuctAll.Count > 0)
			{
				List<XYZ> farestTwoPoints = CreateDuct.GetFarestTwoPoints(new List<XYZ>
				{
					(lstDuctAll[lstDuctAll.Count - 1].Location as LocationCurve).Curve.GetEndPoint(0),
					(lstDuctAll[lstDuctAll.Count - 1].Location as LocationCurve).Curve.GetEndPoint(1),
					(lstDuct[0].Location as LocationCurve).Curve.GetEndPoint(0),
					(lstDuct[0].Location as LocationCurve).Curve.GetEndPoint(1)
				});
				XYZ xyz = farestTwoPoints[0];
				XYZ xyz2 = farestTwoPoints[1];
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(lstDuctAll.Last<Duct>());
				YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(lstDuct[0]);
				double weightOrDiameter = hypiping.GetWeightOrDiameter();
				double weightOrDiameter2 = hypiping2.GetWeightOrDiameter();
				hypiping.GetHeightOrDiameter();
				hypiping2.GetHeightOrDiameter();
				hypiping.GetOffSet();
				hypiping2.GetOffSet();
				if (Math.Round(xyz2.Z, 3, MidpointRounding.AwayFromZero) != Math.Round(xyz.Z, 3, MidpointRounding.AwayFromZero))
				{
					SubTransaction subTransaction = new SubTransaction(doc);
					try
					{
						if (xyz.DistanceTo(xyz2) < (weightOrDiameter / 2.0 + weightOrDiameter2 / 2.0) * 1.5)
						{
							try
							{
								if (hypiping2.IsParallel(lstDuctAll.Last<Duct>()) && !CreateDuct.CreateDuctZhi(cs, new List<Duct>
								{
									lstDuct[0],
									lstDuctAll.Last<Duct>()
								}))
								{
									hyductConnect.NewTransitionFitting(new List<Duct>
									{
										lstDuct[0],
										lstDuctAll.Last<Duct>()
									});
								}
							}
							catch
							{
							}
							return false;
						}
						if (!hypiping2.IsParallel(lstDuctAll.Last<Duct>()))
						{
							return false;
						}
						subTransaction.Start();
						Duct duct = new CreateJigLine().NewDuct(lstDuctAll.Last<Duct>(), xyz2, xyz);
						if (duct != null)
						{
							if (hypiping.BeRotateDuct(duct))
							{
								new YJKPiping<Duct>(duct).Rotate90();
							}
							doc.Regenerate();
							bool flag = hyductConnect.NewElbowFitting(new List<Duct>
							{
								lstDuctAll.Last<Duct>(),
								duct
							});
							doc.Regenerate();
							bool flag2 = hyductConnect.NewElbowFitting(new List<Duct>
							{
								lstDuct[0],
								duct
							});
							if (!flag || !flag2)
							{
								subTransaction.RollBack();
								return false;
							}
							doc.Regenerate();
							subTransaction.Commit();
							return false;
						}
					}
					catch (Exception)
					{
						subTransaction.RollBack();
						return false;
					}
					subTransaction.RollBack();
					return false;
				}
				if (hypiping2.IsParallel(lstDuctAll.Last<Duct>()))
				{
					if (CreateDuct.CreateDuctZhi(cs, new List<Duct>
					{
						lstDuct[0],
						lstDuctAll.Last<Duct>()
					}))
					{
						return true;
					}
					hyductConnect.NewTransitionFitting(new List<Duct>
					{
						lstDuct[0],
						lstDuctAll.Last<Duct>()
					});
				}
				else
				{
					hyductConnect.NewElbowFitting(new List<Duct>
					{
						lstDuct[0],
						lstDuctAll.Last<Duct>()
					});
				}
			}
			return false;
		}

		private static List<XYZ> GetFarestTwoPoints(IList<XYZ> points)
		{
			List<XYZ> list = new List<XYZ>();
			double num = 0.0;
			XYZ item = XYZ.Zero;
			XYZ item2 = XYZ.Zero;
			for (int i = 0; i < points.Count - 1; i++)
			{
				for (int j = i + 1; j < points.Count; j++)
				{
					if (points[i].DistanceTo(points[j]) > num)
					{
						num = points[i].DistanceTo(points[j]);
						item = points[i];
						item2 = points[j];
					}
				}
			}
			list.Add(item);
			list.Add(item2);
			return list;
		}

		public static bool CreateDuctZhi(DuctWindowStruct cs, List<Duct> lstDuct)
		{
			if (cs.dDuctHeight == 0.0)
			{
				Parameter parameter = lstDuct[0].GetParameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM);
				Parameter parameter2 = lstDuct[1].GetParameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM);
				if (parameter == null || parameter2 == null)
				{
					return false;
				}
				double num = parameter.AsDouble() * 304.8;
				double num2 = parameter2.AsDouble() * 304.8;
				return num == num2;
			}
			else
			{
				Parameter parameter3 = lstDuct[0].GetParameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM);
				Parameter parameter4 = lstDuct[0].GetParameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM);
				Parameter parameter5 = lstDuct[1].GetParameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM);
				Parameter parameter6 = lstDuct[1].GetParameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM);
				if (parameter3 == null || parameter4 == null || parameter5 == null || parameter6 == null)
				{
					return false;
				}
				double num3 = parameter3.AsDouble() * 304.8;
				double num4 = parameter4.AsDouble() * 304.8;
				double num5 = parameter5.AsDouble() * 304.8;
				double num6 = parameter6.AsDouble() * 304.8;
				return num3 == num5 && num4 == num6;
			}
		}

		public static XYZ getNewParallelPipeXYZ(XYZ oldXYZ, Line pipeline, double offset, XYZ point)
		{
			XYZ result = null;
			XYZ hyendPoint = pipeline.GetEndPoint(0);
			XYZ hyendPoint2 = pipeline.GetEndPoint(1);
			Line line = YJKLineEx.YJKGetBound(hyendPoint, hyendPoint2);
			if (Math.Abs(hyendPoint.Y - hyendPoint2.Y) < 1E-09)
			{
				if (point.Y > hyendPoint.Y)
				{
					result = new XYZ(oldXYZ.X, oldXYZ.Y + offset / 304.8, oldXYZ.Z);
				}
				else if (point.Y < hyendPoint.Y)
				{
					result = new XYZ(oldXYZ.X, oldXYZ.Y - offset / 304.8, oldXYZ.Z);
				}
			}
			else if (Math.Abs(hyendPoint.X - hyendPoint2.X) < 1E-10)
			{
				if (hyendPoint.X > point.X)
				{
					result = new XYZ(oldXYZ.X - offset / 304.8, oldXYZ.Y, oldXYZ.Z);
				}
				else if (hyendPoint.X < point.X)
				{
					result = new XYZ(oldXYZ.X + offset / 304.8, oldXYZ.Y, oldXYZ.Z);
				}
			}
			else if (hyendPoint.Y != hyendPoint2.Y && hyendPoint.X != hyendPoint2.X)
			{
				double num = Math.Abs((hyendPoint2.X - hyendPoint.X) / line.Length) * (offset / 304.8);
				double num2 = Math.Abs((hyendPoint2.Y - hyendPoint.Y) / line.Length) * (offset / 304.8);
				if (CreateDuct.lookForK(hyendPoint, hyendPoint2) < 1E-06)
				{
					if (CreateDuct.isAnotherSite(hyendPoint, hyendPoint2, point))
					{
						result = new XYZ(oldXYZ.X + num2, oldXYZ.Y + num, oldXYZ.Z);
					}
					else
					{
						result = new XYZ(oldXYZ.X - num2, oldXYZ.Y - num, oldXYZ.Z);
					}
				}
				else if (CreateDuct.lookForK(hyendPoint, hyendPoint2) > 1E-06)
				{
					if (CreateDuct.isAnotherSite(hyendPoint, hyendPoint2, point))
					{
						result = new XYZ(oldXYZ.X - num2, oldXYZ.Y + num, oldXYZ.Z);
					}
					else
					{
						result = new XYZ(oldXYZ.X + num2, oldXYZ.Y - num, oldXYZ.Z);
					}
				}
			}
			return result;
		}

		private static double lookForK(XYZ start, XYZ end)
		{
			double x = start.X;
			double x2 = end.X;
			double y = start.Y;
			return (end.Y - y) / (x2 - x);
		}

		private static bool isAnotherSite(XYZ p1, XYZ p2, XYZ point)
		{
			bool result = false;
			double num = CreateDuct.lookForK(p1, p2);
			if (point.Y - p1.Y - num * (point.X - p1.X) > 0.0)
			{
				result = true;
			}
			return result;
		}

		private static bool blTishi = true;
	}
}
